package com.example.blog.service.impl;

import com.example.blog.config.MailUtil;
import com.example.blog.dao.PostsInfoRepository;
import com.example.blog.dao.UserInfoRepository;
import com.example.blog.dto.*;
import com.example.blog.entity.UserInfo;
import com.example.blog.service.UserInfoService;
import com.example.blog.util.*;
import com.example.blog.vo.RoleAndPermission;
import jdk.internal.dynalink.linker.LinkerServices;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.example.blog.constant.Constant.USER_INFO;
import static com.example.blog.util.TransformationIp.getRealIp;

/**
 * @ClassName: UserInfoServiceImpl
 * @Description: 用户信息实现类

 * @Date 2024/2/1
 * @Version 1.0
 */
@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    UserInfoRepository userInfoRepository;
    @Resource
    RedisUtil redisUtil;
    @Resource
    MailUtil mailUtil;
    @Resource
    PostsInfoRepository postsInfoRepository;
    @Override
    public HashMap getToken(LoginUserDto loginUserDto, HttpServletRequest httpServletRequest) throws Exception {
        HashMap map = new HashMap();
        UserInfo manageInfo = userInfoRepository.findByusernameAndPassword(loginUserDto.getAccount(), loginUserDto.getPassword());
        if (manageInfo == null) {
            return null;
        }
        if (manageInfo.getStatus().equals("2") || manageInfo.getStatus().equals("3")) {
            map.put("errorCode","您的账号已被封号，详情请查看您的邮箱");
            return map;
        }
        return getHashMap(loginUserDto, httpServletRequest, map, manageInfo);
    }

    @Override
    public UserInfo register(UserInfoDto userInfoDto, String realIp) {
        return getUserInfo(userInfoDto,realIp);
    }

    @Override
    public UserInfo update(UserInfo strictMap) {
        UserInfo save = this.userInfoRepository.save(strictMap);
        Set<String> strings = redisUtil.redisLike(strictMap.getId());
        clearCache(strings);
        return save;
    }

    @Override
    public List<RoleAndPermission> getById(String id) {
        List<Map<String,String>> list =  userInfoRepository.findByUserId(id);
        List<RoleAndPermission> roleAndPermissions = ModelMapperUtil.strictMapList(list, RoleAndPermission.class);
        return roleAndPermissions;
    }

    @Override
    public UserInfoD queryByUserId(String userId) {
        UserInfoD userInfoD = new UserInfoD();
        userInfoD.setUserId(userId);
        Optional<UserInfo> byId = userInfoRepository.findById(userId);
        BeanUtils.copyProperties(byId.get(),userInfoD);
        int p = postsInfoRepository.countByUserId(userId);
        userInfoD.setPostCount(p);
        return userInfoD;
    }

    /**
     *  新增用户
     * @param userInfoDto
     * @param realIp
     * @return
     */
    private UserInfo getUserInfo(UserInfoDto userInfoDto, String realIp) {
        UserInfo userInfo = ModelMapperUtil.strictMap(userInfoDto,UserInfo.class);
        UserInfo userInfo1 = userInfoRepository.findByusername(userInfo.getUsername());
        if (userInfo1 != null) {
            return null;
        }
        userInfo.setId(IdUtil.getStringId());
        userInfo.setLoginIp(realIp);
        userInfo.setAddTime(new Date());
        userInfo.setUserType(1);
        userInfo.setLoginTime(new Date());
        userInfo.setStatus("0");
        userInfoRepository.save(userInfo);
        if (StringUtils.isNotEmpty(userInfoDto.getEmail())) {
            MailBean mailBean = new MailBean();
            mailBean.setContent("恭喜你，注册成功");
            mailBean.setSubject("cos2注册");
            mailBean.setRecipient(userInfoDto.getEmail());
            mailUtil.sendSimpleMail(mailBean);
        }
        return userInfo;
    }
    /**
     * 根据强制登录标识符获取token
     * 强制标识符不存在且没有用户登录则直接返回token
     * 用户已登陆则直接返回用户重复登录码
     * @param loginUserDto
     * @param httpServletRequest
     * @param map
     * @param manageInfo
     * @return
     * @throws Exception
     */
    private HashMap getHashMap(LoginUserDto loginUserDto, HttpServletRequest httpServletRequest, HashMap map, UserInfo manageInfo) throws Exception {
        String realIp = getRealIp(httpServletRequest);
        UserDto userDto = ModelMapperUtil.strictMap(manageInfo, UserDto.class);
        // 来源ip
        userDto.setLoginIp(realIp);
        //登录时间
        userDto.setLoginTime(new Date());
        String token = "";
        Boolean isLogin = loginUserDto.getIsLogin();
        Set<String> strings = redisUtil.redisLike(manageInfo.getId());
        if (isLogin != null) {
            if (isLogin) { // 强制登录标识符
                token = UserTokenManager.generateToken(manageInfo.getId());
                clearCache(strings);
                HashMap map1 = setUserInfo(map, manageInfo, userDto, token);
                return map1;
            }
        }
        if (strings.size() >= 1) {
            map.put("errorCode","用户重复登陆");
            return map ;
        }else {
            token = UserTokenManager.generateToken(manageInfo.getId());
            HashMap map1 = setUserInfo(map, manageInfo, userDto, token); //更新用户信息
            return map1;
        }
    }
    /**
     * 清除缓存
     * @param strings
     */
    public void clearCache(Set<String> strings) {
        strings.stream().forEach(
                s -> {
                    String value = redisUtil.getValue(s);
                    try {
                        UserDto userDto1 = JsonXMLUtils.json2obj(value, UserDto.class);
                        redisUtil.leftPush(USER_INFO,JsonXMLUtils.obj2json(userDto1));
                        redisUtil.delete(s);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        );
    }
    /**
     * 更新用户信息并返回token
     * @param map
     * @param manageInfo
     * @param userDto
     * @param token
     * @return
     * @throws Exception
     */
    private HashMap setUserInfo(HashMap map, UserInfo manageInfo, UserDto userDto, String token) throws Exception {
        manageInfo.setLoginTime(userDto.getLoginTime());
        manageInfo.setLoginIp(userDto.getLoginIp());
        userInfoRepository.save(manageInfo);
        redisUtil.setValue(token+manageInfo.getId(), JsonXMLUtils.obj2json(userDto)); // 存入缓存
        map.put("token",token);
        return map;


    }

}
